﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Neturion.Dados;
using Neturion.IRepositorios;
using Neturion.Repositorios;

namespace Neturion.Negocios
{
    public class NegocioMovimentoFinanceiro
    {
        private IRepositorioMovimentoFinanceiro _repositorioMovimentoFinanceiro;
        private NegocioTitulo _negocioTitulo;
        private NegocioFormaPagamento _negocioFormaPagamento;

        public NegocioMovimentoFinanceiro()
        {
            _repositorioMovimentoFinanceiro = new RepositorioMovimentoFinanceiro();
        }

        public MovimentoFinanceiro Inserir(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            _negocioFormaPagamento = new NegocioFormaPagamento();
            //Tirando as Horas das Datas
            Utils.Util.TirarHoraDatasObjetos(ref movimentoFinanceiro);

            //Validar o Movimento Financeiro)
            if(!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Não Validou o Movimento Financeiro");
            }

            //Inserir Situação do Movimento para situação Aberto
            movimentoFinanceiro.EnumSituacaoMovimento = EnumSituacaoMovimento.Aberto; 

            //Verificar se tem Forma de Pagamento e se Esta Força o Vencimento
            if ((movimentoFinanceiro.FormaPagamento != null) && (movimentoFinanceiro.FormaPagamento.ForcarVencimento))
            {
                movimentoFinanceiro.DataVencimento =
                    _negocioFormaPagamento.CalcularDataVencimentoFormaPagamento(movimentoFinanceiro.DataEmissao,
                                                         movimentoFinanceiro.FormaPagamento);
            }

            //Movimento Inserido Já Aceito
            if (movimentoFinanceiro.DataAceitacao.HasValue)
            {
                movimentoFinanceiro = AceitarMovimentoFinanceiro(movimentoFinanceiro, usuarioPermissao);
            }


            //Inserir Cliente ou Forncedor pelo Movimento
            if (movimentoFinanceiro.EnumTipoMovimentoFinanceiro == EnumTipoMovimentoFinanceiro.Pagar)
            {

                //Se for Movimento a Pagar é de um Fornecedor
                NegocioFornecedor negocioFornecedor = new NegocioFornecedor();

                if (negocioFornecedor.ObterPorPessoa(usuarioPermissao, movimentoFinanceiro.PessoaCredorDevedor) == null)
                {
                    Fornecedor fornecedor = new Fornecedor();
                    fornecedor.Pessoa = movimentoFinanceiro.PessoaCredorDevedor;
                    fornecedor.DataCadastro = DateTime.Now.Date;
                    fornecedor.InicioVigenciaFornecedor = DateTime.Now.Date;
                    negocioFornecedor.Inserir(fornecedor);
                }
            }
            else
            {
                //Se for Movimento a Receber é de um Cliente
                NegocioCliente negocioCliente = new NegocioCliente();

                if (negocioCliente.ObterPorPessoa(usuarioPermissao, movimentoFinanceiro.PessoaCredorDevedor) == null)
                {
                    Cliente cliente = new Cliente();
                    cliente.Pessoa = movimentoFinanceiro.PessoaCredorDevedor;
                    cliente.DataCadastro = DateTime.Now.Date;
                    cliente.InicioVigenciaCliente = DateTime.Now.Date;
                    negocioCliente.Inserir(cliente);
                }
            }


            return _repositorioMovimentoFinanceiro.Inserir(movimentoFinanceiro);
        }

        public MovimentoFinanceiro AceitarMovimentoFinanceiro(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            _negocioTitulo = new NegocioTitulo();

            movimentoFinanceiro = AlterarMovimentoParaAceito(movimentoFinanceiro, usuarioPermissao);

            if (movimentoFinanceiro == null)
            {
                throw new Exception("ERRO ao Aceitar Movimento Financeiro!");
            }

            //Se for um MovimentoFinanceiro já Inserido, Atualiza-o, senão devolve-o como está para o Inserir fazer sua parte
            if (movimentoFinanceiro.MovimentoId != 0)
            {
                Atualizar(movimentoFinanceiro,usuarioPermissao);
            }

            return movimentoFinanceiro;
        }

        #region AlterarMovimentoParaAceito
        public MovimentoFinanceiro AlterarMovimentoParaAceito(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            _negocioTitulo = new NegocioTitulo();

            //Validar o Documento
            if ((ValidarMovimentoFinanceiro(movimentoFinanceiro)) && (movimentoFinanceiro.EnumSituacaoMovimento == EnumSituacaoMovimento.Aberto))
            {
                //Mudar a Situação
                movimentoFinanceiro.EnumSituacaoMovimento = EnumSituacaoMovimento.Aceitado;

                //Se não for Selecionada a Data de Aceitação é atribuidada a data do Dia
                movimentoFinanceiro.DataAceitacao = movimentoFinanceiro.DataAceitacao.HasValue
                                                    ? movimentoFinanceiro.DataAceitacao.GetValueOrDefault().Date
                                                    : DateTime.Now.Date;

                //Atribui a Lista de Titulos Geradas ao Movimento Financeiro
                movimentoFinanceiro.ListaTitulos.Clear();
                movimentoFinanceiro.ListaTitulos = _negocioTitulo.GerarTitulosMovimentoFinanceiro(movimentoFinanceiro, usuarioPermissao) as List<Titulo>;
            }
            else
            {
                throw new Exception("ERRO ao Aceitar Movimento Financeiro!");
            }

            return movimentoFinanceiro;
        }
        
        #endregion

        public IList<MovimentoFinanceiro> InserirRotinaMovimentoFinanceiro(MovimentoRotina movimentoRotina, Usuario usuarioPermissao)
        {
            IList<MovimentoFinanceiro> movimentosFinanceiros = null;
            if ((movimentoRotina != null) && (ValidarMovimentoFinanceiro(movimentoRotina.MovimentoFinanceiro)))
            {
                try
                {
                    movimentosFinanceiros = new List<MovimentoFinanceiro>();
                    MovimentoFinanceiro movimentoFinanceiroTmp;
                    //Gerando Movimentos de Acordo o Numero de Movimento Desejado
                    for (int numeroMovimento = 1; numeroMovimento <= movimentoRotina.NumeroMovimentos ; numeroMovimento++)
                    {
                        movimentoFinanceiroTmp = new MovimentoFinanceiro();
                        movimentoFinanceiroTmp.Desconto = movimentoRotina.MovimentoFinanceiro.Desconto;
                        movimentoFinanceiroTmp.DescontoCofins = movimentoRotina.MovimentoFinanceiro.DescontoCofins;
                        movimentoFinanceiroTmp.DescontoCssl = movimentoRotina.MovimentoFinanceiro.DescontoCssl;
                        movimentoFinanceiroTmp.DescontoInss = movimentoRotina.MovimentoFinanceiro.DescontoInss;
                        movimentoFinanceiroTmp.DescontoIr = movimentoRotina.MovimentoFinanceiro.DescontoIr;
                        movimentoFinanceiroTmp.DescontoIss = movimentoRotina.MovimentoFinanceiro.DescontoIss;
                        movimentoFinanceiroTmp.Documento = movimentoRotina.MovimentoFinanceiro.Documento;
                        movimentoFinanceiroTmp.JurosTaxas = movimentoRotina.MovimentoFinanceiro.JurosTaxas;
                        movimentoFinanceiroTmp.EnumTipoMovimentoFinanceiro = movimentoRotina.MovimentoFinanceiro.EnumTipoMovimentoFinanceiro;
                        movimentoFinanceiroTmp.Multa = movimentoRotina.MovimentoFinanceiro.Multa;
                        movimentoFinanceiroTmp.Parcelado = movimentoRotina.MovimentoFinanceiro.Parcelado;
                        movimentoFinanceiroTmp.QuantidadeParcelas = movimentoRotina.MovimentoFinanceiro.QuantidadeParcelas;
                        movimentoFinanceiroTmp.Valor = movimentoRotina.MovimentoFinanceiro.Valor;
                        movimentoFinanceiroTmp.ValidadePagamento = movimentoRotina.MovimentoFinanceiro.ValidadePagamento;
                        movimentoFinanceiroTmp.ContaContabil = movimentoRotina.MovimentoFinanceiro.ContaContabil;
                        movimentoFinanceiroTmp.FonteGeradora = movimentoRotina.MovimentoFinanceiro.FonteGeradora;
                        movimentoFinanceiroTmp.FormaPagamento = movimentoRotina.MovimentoFinanceiro.FormaPagamento;
                        movimentoFinanceiroTmp.PessoaCredorDevedor = movimentoRotina.MovimentoFinanceiro.PessoaCredorDevedor;
                        movimentoFinanceiroTmp.Setor = movimentoRotina.MovimentoFinanceiro.Setor;
                        movimentoFinanceiroTmp.Usuario = movimentoRotina.MovimentoFinanceiro.Usuario;
                        movimentoFinanceiroTmp.Descricao = movimentoRotina.MovimentoFinanceiro.Descricao;

                        //Numero do Movimento na Descrição se for marcada a Flag
                        if((movimentoRotina.NumeroParcelaDescricao)&&(movimentoRotina.NumeroMovimentos > 1))
                        {
                            movimentoFinanceiroTmp.Descricao = movimentoRotina.MovimentoFinanceiro.Descricao + " Rotina " +
                                                               numeroMovimento + " de " +
                                                               movimentoRotina.NumeroMovimentos;
                        }
                        
                        //Numero do Movimento vem por Default no Historico
                        movimentoFinanceiroTmp.Historico = movimentoFinanceiroTmp.Historico + Environment.NewLine + "Rotina " +
                                                               numeroMovimento + " de " +
                                                               movimentoRotina.NumeroMovimentos;
                        //Datas 
                        movimentoFinanceiroTmp.DataCadastro = DateTime.Now.Date;
                        movimentoFinanceiroTmp.DataEmissao = movimentoRotina.MovimentoFinanceiro.DataEmissao;
                        movimentoFinanceiroTmp.DataAceitacao = movimentoRotina.MovimentoFinanceiro.DataAceitacao;
                        movimentoFinanceiroTmp.DataExtorno = null;
                        movimentoFinanceiroTmp.DataQuitado = null;

                        //Numero de Parcelas Aceitas
                        if (movimentoRotina.Aceitos == EnumRotinaAceitos.Nenhum)
                        {
                            movimentoFinanceiroTmp.DataAceitacao = null;
                        }
                        
                        //Verifica se é o Primeiro Movimento para não Incrementar a data de Vencimento
                        if (numeroMovimento == 1)
                        {
                            //Numero de Parcelas Aceitas
                            if(movimentoRotina.Aceitos != EnumRotinaAceitos.Nenhum)
                            {
                                movimentoFinanceiroTmp.DataAceitacao = movimentoRotina.MovimentoFinanceiro.DataAceitacao.HasValue 
                                                                        ? movimentoRotina.MovimentoFinanceiro.DataAceitacao.GetValueOrDefault().Date 
                                                                        : DateTime.Today;
                            }

                            //Data de Vencimento
                            movimentoFinanceiroTmp.DataVencimento = movimentoRotina.MovimentoFinanceiro.DataVencimento;
                        }
                        else
                        {
                            //Geração dos Documentos de Rotinas
                            //Numero de Parcelas Aceitas
                            if (movimentoRotina.Aceitos == EnumRotinaAceitos.Todos)
                            {
                                movimentoFinanceiroTmp.DataAceitacao = movimentoRotina.MovimentoFinanceiro.DataAceitacao.HasValue 
                                                                        ? movimentoRotina.MovimentoFinanceiro.DataAceitacao.GetValueOrDefault().Date   
                                                                        : DateTime.Now.Date; 
                            }

                            //Incrementando o Vencimento a partir da Segunda Rodada por isso é -1 
                            movimentoFinanceiroTmp.DataVencimento = movimentoRotina.MovimentoFinanceiro.DataVencimento.AddMonths((int)movimentoRotina.Periodicidade * (numeroMovimento - 1));
                        }

                        //Inserir o Movimento
                        movimentosFinanceiros.Add(Inserir(movimentoFinanceiroTmp, usuarioPermissao));
                    }
                }
                catch (Exception)
                {
                    
                    throw new Exception("Erro ao Criar Rotina");
                }
            }
            else
            {
                throw new Exception("Erro ao Criar Rotina");
            } 

            return movimentosFinanceiros;
        }

        public bool ValidarMovimentoFinanceiro(MovimentoFinanceiro movimentoFinanceiro)
        {
            Boolean retorno = true;
            //Rotina de Validação do Movimento
            if (movimentoFinanceiro == null)
            {
                throw new Exception("Não Validou o Movimento Financeiro");
                retorno = false;
            }

            //Se pessoa for Nula
            if ((movimentoFinanceiro != null) && (movimentoFinanceiro.PessoaCredorDevedor == null))
            {
                retorno = false;
                throw new Exception("Não Validou o Movimento Financeiro");
            }

            //se tiver Forma de Pagamento A mesma deve ser permitida para o tipo de Movimento
            if ((movimentoFinanceiro.FormaPagamento != null) && (movimentoFinanceiro.FormaPagamento.EnumTipoMovimentoFinanceiro != movimentoFinanceiro.EnumTipoMovimentoFinanceiro))
            {
                retorno = false;
                throw new Exception("Forma de Pagamento não Permitida para o Tipo de Movimento!");
            }

            return retorno;
        }

        public MovimentoFinanceiro Atualizar(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            _negocioFormaPagamento = new NegocioFormaPagamento();
            //Tirando as Horas das Datas
            Utils.Util.TirarHoraDatasObjetos(ref movimentoFinanceiro);

            //Validar o Movimento Financeiro
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Não Validou o Movimento Financeiro");
            }

            //Verificar se tem Forma de Pagamento e se Esta Força o Vencimento
            if ((movimentoFinanceiro.FormaPagamento != null) && (movimentoFinanceiro.FormaPagamento.ForcarVencimento))
            {
                movimentoFinanceiro.DataVencimento =
                    _negocioFormaPagamento.CalcularDataVencimentoFormaPagamento(movimentoFinanceiro.DataEmissao,
                                                         movimentoFinanceiro.FormaPagamento);
            }

            //Movimento Atualizado já Aceito e Não foi Chamado o Processo pelo Aceitar 
            if ((movimentoFinanceiro.DataAceitacao.HasValue)&&(movimentoFinanceiro.EnumSituacaoMovimento == EnumSituacaoMovimento.Aberto))
            {
                movimentoFinanceiro = AlterarMovimentoParaAceito(movimentoFinanceiro, usuarioPermissao);
            }

            //Inserir Cliente ou Forncedor pelo Movimento
            if (movimentoFinanceiro.EnumTipoMovimentoFinanceiro == EnumTipoMovimentoFinanceiro.Pagar)
            {

                //Se for Movimento a Pagar é de um Fornecedor
                NegocioFornecedor negocioFornecedor = new NegocioFornecedor();

                if (negocioFornecedor.ObterPorPessoa(usuarioPermissao, movimentoFinanceiro.PessoaCredorDevedor) == null)
                {
                    Fornecedor fornecedor = new Fornecedor();
                    fornecedor.Pessoa = movimentoFinanceiro.PessoaCredorDevedor;
                    fornecedor.DataCadastro = DateTime.Now.Date;
                    fornecedor.InicioVigenciaFornecedor = DateTime.Now.Date;
                    negocioFornecedor.Inserir(fornecedor);
                }
            }
            else
            {
                //Se for Movimento a Receber é de um Cliente
                NegocioCliente negocioCliente = new NegocioCliente();

                if (negocioCliente.ObterPorPessoa(usuarioPermissao, movimentoFinanceiro.PessoaCredorDevedor) == null)
                {
                    Cliente cliente = new Cliente();
                    cliente.Pessoa = movimentoFinanceiro.PessoaCredorDevedor;
                    cliente.DataCadastro = DateTime.Now.Date;
                    cliente.InicioVigenciaCliente = DateTime.Now.Date;
                    negocioCliente.Inserir(cliente);
                }
            }

            return _repositorioMovimentoFinanceiro.Atualizar(movimentoFinanceiro);
        }

        public MovimentoFinanceiro AjustarMovimentoFinanceiro(MovimentoAjuste movimentoAjuste, Usuario usuarioPermissao)
        {
            _negocioTitulo = new NegocioTitulo();
            
            //Lista para pegar os Titulos Gerados
            IList<Titulo> listaTitulosAjuste = new List<Titulo>();

            //Validar o Movimento Financeiro
            if (!ValidarMovimentoFinanceiro(movimentoAjuste.MovimentoFinanceiro))
            {
                throw new Exception("Não Validou o Movimento Financeiro");
            }

            //Se o Movimento estiver Estornado Não pode Ajustar
            if (movimentoAjuste.MovimentoFinanceiro.EnumSituacaoMovimento == EnumSituacaoMovimento.Extornado)
            {
                throw new Exception("Não pode Ajustar Movimento Financeiro Estornado");
            }

            //Movimento para Ser Alterado o Valor e Incluir o Novo Titulo
            MovimentoFinanceiro movimentoFinanceiroAjustado = Utils.Util.Clonar(movimentoAjuste.MovimentoFinanceiro,null,null);
           
            //Movimento para ser gerado os Titulos
            MovimentoFinanceiro movimentoFinanceiroAjuste = Utils.Util.Clonar(movimentoAjuste.MovimentoFinanceiro, null, null);
  
            //Geração dos Titulos de Ajuste (Alteração no Movimento de Ajuste)
            movimentoFinanceiroAjuste.Valor = movimentoAjuste.ValorAjuste;
            movimentoFinanceiroAjuste.DataVencimento = movimentoAjuste.Vencimento; //Casos Futuros de Ajustes Multiplos (O Vencimento Será Incrementado)
            movimentoFinanceiroAjuste.Parcelado = false; //Casos Futuros de Ajustes Multiplos (Manten Parcelado false)
            movimentoFinanceiroAjuste.QuantidadeParcelas = 1; //Casos Futuros de Ajustes Multiplos (Altera a Quantidade de Ajustes)

            //Retira o Nome Ajuste do movimento
            if (movimentoFinanceiroAjuste.Descricao.Contains("(Ajustado)"))
            {
                movimentoFinanceiroAjuste.Descricao =  movimentoFinanceiroAjuste.Descricao.Replace(" (Ajustado)","");
            }

            movimentoFinanceiroAjuste.Descricao += " (Ajuste)";
            movimentoFinanceiroAjuste.Historico += " (Ajuste)";
            movimentoFinanceiroAjuste.Documento += " " + movimentoAjuste.Documento;

            //Geração dos Titulos do Ajuste e passados para a lista//
            listaTitulosAjuste = _negocioTitulo.GerarTitulosMovimentoFinanceiro(movimentoFinanceiroAjuste,usuarioPermissao);
            //Geração dos Titulos de Ajuste (Alteração no Movimento de Ajuste)

            //Alteração no Movimento Ajustado para ser Salvo
            //Passagem da Lista de Titulos do Ajuste (Feito Assim para Casos Futuros de Ajustes Multiplos)
            foreach (Titulo titulo in listaTitulosAjuste)
            {
                movimentoFinanceiroAjustado.AdicionarTitulo(titulo);
                
                //Valor do Movimento somado ao valor dos Novos Titulos
                movimentoFinanceiroAjustado.Valor += titulo.Valor;
            }

            //Descrição Movimento 
            if (!movimentoFinanceiroAjustado.Descricao.Contains("(Ajustado)"))
            {
                movimentoFinanceiroAjustado.Descricao += " (Ajustado)";
                movimentoFinanceiroAjustado.Historico += " (Ajustado) " + movimentoAjuste.Documento;
            }
           
            
            //Abrir o Movimento
            movimentoFinanceiroAjustado = AbrirMovimentoFinanceiro(movimentoFinanceiroAjustado, usuarioPermissao);

            return movimentoFinanceiroAjustado;
        }

        public MovimentoFinanceiro QuitarMovimentoFinanceiro(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            //Validar Movimento
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Quitar Movimento");
            }

            //Se o Movimento tiver Todos os outros Titulos Quitados
            bool quitar = true;
            foreach (Titulo tituloTmp in movimentoFinanceiro.ListaTitulos)
            {
                //Se tem algum tiulo com situação de aberto ou ParcialmenteQuitado que não seja este que está sendo quitado agora  
                //(Verificar situações de estornado no futuro)
                if ((tituloTmp.EnumSituacaoMovimento == EnumSituacaoMovimento.Aberto)||(tituloTmp.EnumSituacaoMovimento == EnumSituacaoMovimento.ParcialmenteQuitado))
                {
                    quitar = false;
                }
            }
            //Se não tiver nenhum titulo aberto quita o Movimento
            if (quitar)
            {
                //Data da Quitação do Movimento
                movimentoFinanceiro.DataQuitado = DateTime.Now.Date;

                //Situação 
                movimentoFinanceiro.EnumSituacaoMovimento = EnumSituacaoMovimento.Quitado;
            }
            else
            {
                //Data da Quitação do Movimento
                movimentoFinanceiro.DataQuitado = null;

                //Situação 
                movimentoFinanceiro.EnumSituacaoMovimento = EnumSituacaoMovimento.ParcialmenteQuitado;
            }

            movimentoFinanceiro.Usuario = usuarioPermissao;

            return _repositorioMovimentoFinanceiro.Atualizar(movimentoFinanceiro);
        }

        public MovimentoFinanceiro AbrirMovimentoFinanceiro(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            //Validar Movimento
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Quitar Movimento");
            }

            //Se o Movimento tiver algum outro Titulos Quitados ou ParcialmenteQuitado
            bool quitar = false;
            foreach (Titulo tituloTmp in movimentoFinanceiro.ListaTitulos)
            {
                //(Verificar situações de estornado no futuro)
                if ((tituloTmp.EnumSituacaoMovimento == EnumSituacaoMovimento.Quitado) || (tituloTmp.EnumSituacaoMovimento == EnumSituacaoMovimento.ParcialmenteQuitado))
                {
                    quitar = true;
                }
            }
           
            //Se tiver algum titulo quitado ou ParcialmenteQuitado a Sitação é ParcialmenteQuitado
            movimentoFinanceiro.EnumSituacaoMovimento = quitar ? EnumSituacaoMovimento.ParcialmenteQuitado : EnumSituacaoMovimento.Aceitado;

            //Data da Quitação do Movimento
            movimentoFinanceiro.DataQuitado = null;

            movimentoFinanceiro.Usuario = usuarioPermissao;

            return _repositorioMovimentoFinanceiro.Atualizar(movimentoFinanceiro);
        }

        public MovimentoFinanceiro EstornarMovimentoFinanceiro(MovimentoFinanceiro movimentoFinanceiro, Usuario usuarioPermissao)
        {
            //MovimentoFinanceiro movimentoFinanceiroTmp = null;

            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Validar o Movimento!");
            }

            if ((movimentoFinanceiro.EnumSituacaoMovimento == EnumSituacaoMovimento.Inserindo)
              || (movimentoFinanceiro.EnumSituacaoMovimento == EnumSituacaoMovimento.Extornado))
            {
                throw new Exception("Movimento está com a Situação de " + movimentoFinanceiro.EnumSituacaoMovimento.ToString() + ", NÃO permitindo o estorno do mesmo.");
            }

            //Estornar Titulos
            if (TitulosValidosMovimento(movimentoFinanceiro).Count > 0)
            {
                _negocioTitulo = new NegocioTitulo();
                foreach (Titulo titulo in TitulosValidosMovimento(movimentoFinanceiro))
                {
                    _negocioTitulo.EstornarTitulo(titulo, usuarioPermissao);
                }
            }

            movimentoFinanceiro.DataExtorno = DateTime.Now.Date;
            movimentoFinanceiro.EnumSituacaoMovimento = EnumSituacaoMovimento.Extornado;

            return Atualizar(movimentoFinanceiro,usuarioPermissao);
        }

        public List<Titulo> TitulosValidosMovimento(MovimentoFinanceiro movimentoFinanceiro)
        {
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Validar o Movimento!");
            }

            return movimentoFinanceiro.ListaTitulos.Cast<Titulo>().ToList()
                .Where((titulo => (titulo.EnumSituacaoMovimento != EnumSituacaoMovimento.Extornado))).ToList();
        }

        public List<Titulo> TitulosQuitadosMovimento(MovimentoFinanceiro movimentoFinanceiro)
        {
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                 throw new Exception("Erro ao Validar o Movimento!");
            }

            return movimentoFinanceiro.ListaTitulos.Cast<Titulo>().ToList()
                .Where((titulo => (titulo.EnumSituacaoMovimento == EnumSituacaoMovimento.Quitado))).ToList();
        }

        public List<Titulo> TitulosAbertosMovimento(MovimentoFinanceiro movimentoFinanceiro)
        {
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Validar o Movimento!");
            }

            return movimentoFinanceiro.ListaTitulos.Cast<Titulo>().ToList()
                .Where(
                    (
                    titulo =>
                        (titulo.EnumSituacaoMovimento == EnumSituacaoMovimento.Aberto)
                    || (titulo.EnumSituacaoMovimento == EnumSituacaoMovimento.ParcialmenteQuitado)
                    )
                    ).ToList();
        }

        public decimal ValorSaldoMovimento(MovimentoFinanceiro movimentoFinanceiro)
        {
            _negocioTitulo = new NegocioTitulo();
            return TitulosAbertosMovimento(movimentoFinanceiro).Sum(titulo => _negocioTitulo.ValorSaldoTitulo(titulo));
        }

        public int QuantidadeTitulosAbertosMovimento(MovimentoFinanceiro movimentoFinanceiro)
        {
            if (!ValidarMovimentoFinanceiro(movimentoFinanceiro))
            {
                throw new Exception("Erro ao Validar o Movimento!");
            }

            return movimentoFinanceiro.ListaTitulos.Cast<Titulo>().ToList()
                .Where(
                    (
                    titulo =>
                        (titulo.EnumSituacaoMovimento == EnumSituacaoMovimento.Aberto)
                    )
                    ).Count();
        }
     
        public void Excluir(MovimentoFinanceiro movimentoFinanceiro)
        {
            MovimentoFinanceiro movimentoFinanceiroTmp = ObterPorId(movimentoFinanceiro.MovimentoId);
            _repositorioMovimentoFinanceiro.Excluir(movimentoFinanceiroTmp);
        }

        public IList<MovimentoFinanceiro> ObterTodos()
        {
            return _repositorioMovimentoFinanceiro.ObterTodos();
        }

        public IList<MovimentoFinanceiro> ObterTodos(int inicio, int quantidade, int quantidadeMinima, Usuario usuarioPermissao, EnumTipoMovimentoFinanceiro enumTipoMovimentoFinanceiro, string documento, long numeroMovimento, string descricao, EnumSituacaoMovimento enumSituacaoMovimento, bool parcelado, Pessoa credorDevedor, Setor setor, FonteGeradora fonteGeradora, ContaContabil contaContabil, DateTime? emissaoDe, DateTime? emissaoAte, DateTime? vencimentoDe, DateTime? vencimentoAte, DateTime? aceitoDe, DateTime? aceitoAte, DateTime? quitadoDe, DateTime? quitadoAte, DateTime? estornadoDe, DateTime? estornadoAte, decimal valorDe, decimal valorAte, FormaPagamento formaPagamento, TipoFormaPagamento tipoFormaPagamento)
        {
            IEnumerable<MovimentoFinanceiro> enumerable =
            _repositorioMovimentoFinanceiro.ObterTodos(inicio, quantidade, quantidadeMinima, enumTipoMovimentoFinanceiro, documento, numeroMovimento, descricao, enumSituacaoMovimento, parcelado, credorDevedor, setor, fonteGeradora, contaContabil, emissaoDe, emissaoAte, vencimentoDe, vencimentoAte, aceitoDe, aceitoAte, quitadoDe, quitadoAte, estornadoDe, estornadoAte, valorDe, valorAte, formaPagamento, tipoFormaPagamento).ToList().Distinct();
            return enumerable.ToList();
        }

        public MovimentoFinanceiro ObterPorId(long id)
        {
            return _repositorioMovimentoFinanceiro.ObterPorId(id);
        }
    }
}